/*
 * Copyright (c) 2011. This file is public under GPLv3 license.
 * For more information about license please refer to http://www.gnu.org/licenses/gpl.html
 */

package com.freetools.watchdog.engine;

import com.freetools.watchdog.commands.CommandFactory;
import com.freetools.watchdog.model.ICommand;
import com.freetools.watchdog.model.IModelHolder;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Parses command line to separate commands and their parameters.
 * Parameters should be divided by space symbols.
 * To escape spaces wrap parameter by quote symbols.
 * <br/>
 * <br/>
 * For example:
 * <br/>
 * <code>-file "./log file.log"</code>
 * <br/>
 * <br/>
 * In figure braces contains parameter format it is used in {@link com.freetools.watchdog.commands.ColumnsCmd}
 * to determinate time parsing rule.
 * <br/>
 * <br/>
 * For example:
 * <br/>
 * <code>-columns time[*timestamp]{yyyy-MM-dd HH:mm:ss,SSS}</code>
 *
 * @author Michael Morozov
 * @see com.freetools.watchdog.commands.ColumnsCmd
 * @see com.freetools.watchdog.commands.DBCmd
 * @see com.freetools.watchdog.commands.FileCmd
 * @see com.freetools.watchdog.commands.ExitCmd
 * @see com.freetools.watchdog.commands.HelpCmd
 * @see com.freetools.watchdog.commands.ParseCmd
 * @see com.freetools.watchdog.commands.QueryCmd
 * @see com.freetools.watchdog.commands.RunCmd
 * @see com.freetools.watchdog.commands.SortCmd
 * @see com.freetools.watchdog.commands.SpoolCmd
 * @see com.freetools.watchdog.commands.SQLCmd
 */
public class CommandParser
{
    private static Pattern COMMAND_PATTERN;
    private static final Pattern PARAM_PATTERN = Pattern.compile("(\".*?\"|\\S+\\{.*?\\}|\\S+)");

    public static void parseCommandLineAndFillModel(String commandLine, IModelHolder model)
    {

        if (COMMAND_PATTERN == null)
        {
            StringBuilder names = new StringBuilder();
            for (String commandName : CommandFactory.getCommandsNames())
            {
                names.append(commandName).append("|");
            }
            names.deleteCharAt(names.length() - 1);
            COMMAND_PATTERN = Pattern.compile(String.format("-(%1$s)\\s*(.*?(?=\\s-(?:%1$s)|\\z))", names));
        }


        Matcher matcher = COMMAND_PATTERN.matcher(commandLine);
        while (matcher.find())
        {
            String commandName = matcher.group(1);
            String bigParameter = matcher.group(2);
            ICommand command = CommandFactory.createCommand(commandName);
            model.getCommands().add(command);
            if (command.isMultipleParametrized())
            {
                Matcher paramMatcher = PARAM_PATTERN.matcher(bigParameter);
                while (paramMatcher.find())
                {
                    if (paramMatcher.group(1).length() > 0)
                    {
                        command.getParameters().add(paramMatcher.group(1));
                    }
                }
            } else
            {
                String trimmedParam = bigParameter.trim();
                if (trimmedParam.length() > 0)
                    command.getParameters().add(trimmedParam);
            }
        }

    }
}